package com.billionsfinance.hessian.core;

import com.billionsfinance.hessian.common.anno.HessianPath;
import com.billionsfinance.hessian.common.utils.ZkConfig;
import com.billionsfinance.hessian.model.ServerInfo;
import org.apache.commons.lang3.time.StopWatch;
import org.reflections.Reflections;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.util.Assert;

import java.util.*;
import java.util.concurrent.TimeUnit;


public abstract class HessianInitFactory implements DisposableBean {

	private Logger LOGGER = LoggerFactory.getLogger(getClass());

	/**
	 * 扫描包
	 */
	protected String[] scanPackages;

	/**
	 * zookeeper配置信息
	 */
	protected ZkConfig zkConfig;

	/**
	 * 初始化Hessian信息
	 */
	private void init() {
		LOGGER.info("开始初始化zookeeper-Hessian配置信息");
		Assert.notNull(scanPackages, "scanPackages can not be null");
		Assert.notNull(zkConfig, "zkConfig can not be null");
		StopWatch watch = StopWatch.createStarted();
		starterZookeeper();
		watch.stop();
		LOGGER.info("初始化zookeeper-Hessian配置信息成功,耗时{}ms", watch.getTime(TimeUnit.MILLISECONDS));
	}

	protected Set<ServerInfo> scanPackages(String accessUrl) {
		Set<ServerInfo> serverInfoSet = new HashSet<>();
		List<String> scan = Arrays.asList(scanPackages);
		LOGGER.info("初始化扫描Hessian信息开始！包路径:{}", scan);
		Reflections reflections = new Reflections(scan);
		Set<Class<?>> classSet = reflections.getTypesAnnotatedWith(HessianPath.class);
		cacheHessianServer(classSet);
		for (Class<?> clazz : classSet) {
			if (clazz.isInterface()) {
				HessianPath hessianPath = clazz.getAnnotation(HessianPath.class);

				String value = hessianPath.value();
				String group = hessianPath.group();
				String edition = hessianPath.edition();
				String createBy = hessianPath.createBy();
				int connTimeout = hessianPath.connTimeout();
				int readTimeout = hessianPath.readTimeout();

				String simpleName = clazz.getSimpleName();
				String name = clazz.getName();

				ServerInfo info = new ServerInfo(group, edition, simpleName, name, createBy, value, accessUrl, connTimeout, readTimeout);
				serverInfoSet.add(info);
			}
		}
		return serverInfoSet;
	}

	private void cacheHessianServer(Set<Class<?>> classSet) {
		Set<Class<?>> interfaceSet = new HashSet<>();
		Set<Class<?>> serverSet = new HashSet<>();
		for (Class<?> clazz : classSet) {
			if (clazz.isInterface()) {
				interfaceSet.add(clazz);
			} else {
				serverSet.add(clazz);
			}
		}

		for (Class<?> clazz : interfaceSet) {
			for (Class<?> server : serverSet) {
				if (clazz.isAssignableFrom(server)) {
					HessianCacheManager.setHessianServerInfo(clazz, server);
				}
			}
		}
	}

	/**
	 * 初始化Hessian数据
	 */
	protected abstract void starterZookeeper();

	public void setScanPackages(String[] scanPackages) {
		this.scanPackages = scanPackages;
	}

	public void setZkConfig(ZkConfig zkConfig) {
		this.zkConfig = zkConfig;
	}

}